package com.brillilab.service.core.elsearch.impl;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.brillilab.domain.pa.kit.ReagentSearchField;
import com.brillilab.domain.pa.kit.ReagentSearchPa;
import com.brillilab.domain.po.elsearch.EsReagent;
import com.brillilab.elsearch.constants.ElsearchConfig;
import com.brillilab.elsearch.reponsitories.EsReagentRepository;
import com.brillilab.elsearch.utils.ElsearchUtils;
import com.brillilab.service.constant.ServiceConstant;
import com.brillilab.service.core.elsearch.IEsReagentService;

@Service
@Transactional
public class EsReagentServiceImpl implements IEsReagentService {

    @Autowired
    private EsReagentRepository esReagentRepository;
    @Autowired
    private ElsearchConfig elsearchConfig;

    @Override
    public EsReagent queryById(Long kitId) {
        return esReagentRepository.findById(kitId).orElse(null);
    }

    @Override
    public EsReagent save(EsReagent eb) {
        return esReagentRepository.save(eb);
    }

    @Override
    public boolean batchSave(List<EsReagent> esList) {
        List<EsReagent> list=(List<EsReagent>) esReagentRepository.saveAll(esList);
        return list.size() == esList.size();
    }

    @Override
    public Page<EsReagent> queryList(ReagentSearchPa pa) {
    	List<ReagentSearchField> fieldList = pa.getSearchFieldList();
        Long labId=pa.getLabId();
        Long labMemberId=pa.getLabMemberId();

        String searchName=pa.getSearchName();
        String company=pa.getCompany();
        Integer zone=pa.getZone();
        Long reagentTypeId=pa.getReagentTypeId();
        List<Long> reagentTypeIds=pa.getReagentTypeIds();

        Assert.notNull(labId,"labId不能为空");

        Pageable pageable=PageRequest.of(
                ((int) pa.getPageNum() - 1) >= 0 ? (int) pa.getPageNum() - 1 : 1,
                (int) pa.getPageSize() > 0 ? (int) pa.getPageSize() : 10
        );

        BoolQueryBuilder builder=QueryBuilders.boolQuery();
        builder.must(QueryBuilders.termQuery("isDelete",0));
        builder.must(QueryBuilders.termQuery("labId",labId));

        if(labMemberId != null){
            builder.must(QueryBuilders.termQuery("labMemberId",labMemberId));
        }

        if(StringUtils.isNotBlank(searchName)){
            searchName=searchName.trim();
            builder.must(QueryBuilders.boolQuery()
                    .should(QueryBuilders.boolQuery()
                            .should(QueryBuilders.matchPhrasePrefixQuery("kitName",searchName).analyzer(elsearchConfig.getChineseAnalyzer()).boost(elsearchConfig.getPhrasePrefixBoost()))
                            .should(QueryBuilders.matchPhraseQuery("kitName",searchName).analyzer(elsearchConfig.getChineseAnalyzer()).slop(1).boost(elsearchConfig.getPhrasePrefixBoost()))
                            .should(QueryBuilders.matchQuery("kitName",searchName).analyzer(elsearchConfig.getChineseAnalyzer()).operator(Operator.AND).boost(elsearchConfig.getMatchAndBoost()))
                            .should(QueryBuilders.wildcardQuery("kitName.keyword",ElsearchUtils.getWildCardQauryValue(searchName)).boost(elsearchConfig.getBoostOne()))
                            .boost(5)
                    )
                    .should(QueryBuilders.boolQuery()
                            .should(QueryBuilders.matchPhrasePrefixQuery("alias",searchName).analyzer(elsearchConfig.getChineseAnalyzer()).boost(elsearchConfig.getPhrasePrefixBoost()))
                            .should(QueryBuilders.matchPhraseQuery("alias",searchName).analyzer(elsearchConfig.getChineseAnalyzer()).slop(1).boost(elsearchConfig.getPhrasePrefixBoost()))
                            .should(QueryBuilders.matchQuery("alias",searchName).analyzer(elsearchConfig.getChineseAnalyzer()).operator(Operator.AND).boost(elsearchConfig.getMatchAndBoost()))
                            .should(QueryBuilders.wildcardQuery("alias.keyword",ElsearchUtils.getWildCardQauryValue(searchName)).boost(elsearchConfig.getBoostOne()))
                            .boost(2)
                    )
                    .should(QueryBuilders.boolQuery()
                            .should(QueryBuilders.wildcardQuery("itemNo",ElsearchUtils.getWildCardQauryValue(searchName)))
                            .boost(2)
                    )
            ).boost(5);
        }

        if(StringUtils.isNotBlank(company)){
            company=company.trim();
            builder.must(
                    QueryBuilders.matchPhrasePrefixQuery("company",company).analyzer(elsearchConfig.getChineseAnalyzer()).boost(elsearchConfig.getPhrasePrefixBoost())
            ).boost(2);
        }

        if(zone != null){
            builder.must(QueryBuilders.termQuery("zone",zone)).boost(2);
        }

        if(!CollectionUtils.isEmpty(reagentTypeIds)){
            builder.must(QueryBuilders.termsQuery("reagentTypeId",reagentTypeIds)).boost(2);
        }


        //抗体试剂搜索条件
        if(!CollectionUtils.isEmpty(fieldList) && ServiceConstant.antibody_reagent_type_id.equals(reagentTypeId)){
            BoolQueryBuilder boolQuery=QueryBuilders.boolQuery();
            boolQuery.must(QueryBuilders.termQuery("reagents.isDelete",0));
            if(StringUtils.isNotBlank(pa.getFieldValue("antigenTarget"))){
                boolQuery.must(QueryBuilders.wildcardQuery("reagents.antigenTarget",ElsearchUtils.getWildCardQauryValue(pa.getFieldValue("antigenTarget").trim()))).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("cloneNo"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.cloneNo",pa.getFieldValue("cloneNo").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("application"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.applicationAn",pa.getFieldValue("application").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("hostSource"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.hostSource",pa.getFieldValue("hostSource").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("reactivity"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.reactivity",pa.getFieldValue("reactivity").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("biologicalAgent"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.biologicalAgent",pa.getFieldValue("biologicalAgent").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("coupling"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.coupling",pa.getFieldValue("coupling").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("cloneType"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.cloneType",pa.getFieldValue("cloneType").trim())).boost(2);
            }
            builder.must(QueryBuilders.nestedQuery("reagents",boolQuery,ScoreMode.Total));
        }

        //引物试剂搜索条件
        if(!CollectionUtils.isEmpty(fieldList) && ServiceConstant.primer_reagent_type_id.equals(reagentTypeId)){
            BoolQueryBuilder boolQuery=QueryBuilders.boolQuery();
            boolQuery.must(QueryBuilders.termQuery("reagents.isDelete",0));
            if(StringUtils.isNotBlank(pa.getFieldValue("primerName"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.primerName",pa.getFieldValue("primerName").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("application"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.applicationPr",pa.getFieldValue("application").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("species"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.species",pa.getFieldValue("species").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("region"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.region",pa.getFieldValue("region").trim())).boost(2);
            }
            builder.must(QueryBuilders.nestedQuery("reagents",boolQuery,ScoreMode.Total));
        }

        //质粒试剂搜索条件
        if(!CollectionUtils.isEmpty(fieldList) && ServiceConstant.plasmid_reagent_type_id.equals(reagentTypeId)){
            BoolQueryBuilder boolQuery=QueryBuilders.boolQuery();
            boolQuery.must(QueryBuilders.termQuery("reagents.isDelete",0));
            if(StringUtils.isNotBlank(pa.getFieldValue("skeletonPlasmidName"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.skeletonPlasmidName",pa.getFieldValue("skeletonPlasmidName").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("promoter"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.promoter",pa.getFieldValue("promoter").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("classify"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.classify",pa.getFieldValue("classify").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("prokaryoticResistance"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.prokaryoticResistance",pa.getFieldValue("prokaryoticResistance").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("eukaryoticResistance"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.eukaryoticResistance",pa.getFieldValue("eukaryoticResistance").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("label"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.label",pa.getFieldValue("label").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("clonedHost"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.clonedHost",pa.getFieldValue("clonedHost").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("expressionHost"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.expressionHost",pa.getFieldValue("expressionHost").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("copyLevel"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.copyLevel",pa.getFieldValue("copyLevel").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("plasmidType"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.plasmidType",pa.getFieldValue("plasmidType").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("constitutive"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.constitutive",pa.getFieldValue("constitutive").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("inductionMethod"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.inductionMethod",pa.getFieldValue("inductionMethod").trim())).boost(2);
            }
            if(StringUtils.isNotBlank(pa.getFieldValue("clonedMethod"))){
                boolQuery.must(QueryBuilders.matchPhrasePrefixQuery("reagents.clonedMethod",pa.getFieldValue("clonedMethod").trim())).boost(2);
            }
            builder.must(QueryBuilders.nestedQuery("reagents",boolQuery,ScoreMode.Total));
        }

        return esReagentRepository.search(builder,pageable);
    }

}
